home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 145 / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin / tools / sharp / sxwork3.lzh / サンプル実用編 / 爆弾ゲーム / BOMB.C < prev    next >
Text File  |  1994-03-10  |  37KB  |  1,233 lines

  1. /******************************************************************************
  2.  *    bomb.c:        爆弾ゲームの処理関数
  3.  ******************************************************************************
  4.  *    Workroom SX-68K Sample Program Copyright 1994 SHARP
  5.  *
  6.  *    機能説明:
  7.  *    セルの描画,マップの作成,タイマー処理,当たり判定などなどの処理を
  8.  *    行います。
  9.  */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <sxmemory.h>        /* メモリマンを利用するときに必要    */
  14. #include <event.h>        /* イベントマンを利用するときに必要    */
  15. #include <sxgraph.h>        /* グラフ系マネージャを利用するときに必要 */
  16. #include <window.h>        /* ウィンドウマンを利用するときに必要    */
  17. #include <dialog.h>        /* ダイアログマンを利用するときに必要    */
  18. #include <text.h>        /* テキストマンを利用するときに必要    */
  19. #include <task.h>        /* タスクマンを利用するときに必要    */
  20. #include "bomb.h"        /* このプログラム固有のヘッダファイル    */
  21.  
  22. /******************************************************************************
  23.  *    getGrid():    マウスグリッドポインタがセルマップ上かどうかを調べる
  24.  ******************************************************************************
  25.  *    引数:    ComVal *pcv    共通変数へのポインタ
  26.  *        LPoint lpt    ポインタ座標
  27.  *        CPoint *pcpt    セルマップ上のグリッドへのポインタ
  28.  *    戻り値:    BOOLEAN        = TRUE:  グリッドポインタはセルマップの中
  29.  *                = FALSE: グリッドポインタはセルマップの外
  30.  *    注釈:    セルマップ上であったなら、そのグリッドポインタを求める。
  31.  */
  32. BOOLEAN getGrid(ComVal *pcv, LPoint lpt, CPoint *pcpt)
  33. {
  34.     Rect rc;
  35.  
  36.     rc = pcv->windowPtr->graph.rect;
  37.     rc.d.top += MARGIN * 2 + INFO_HEIGHT;
  38.     rc.d.left += MARGIN;
  39.     rc.d.bottom -= MARGIN;
  40.     rc.d.right -= MARGIN;
  41.  
  42.     if (!GMPtInRect(&rc, lpt))
  43.         return FALSE;
  44.  
  45.     pcpt->x = (HIWORD(lpt) - MARGIN) / 16;
  46.     pcpt->y = (LOWWORD(lpt) - (MARGIN * 2 + INFO_HEIGHT)) / 16;
  47.  
  48.     return TRUE;
  49. }
  50.  
  51. /******************************************************************************
  52.  *    drawCell():    セルマップの再描画処理
  53.  ******************************************************************************
  54.  *    引数:    ComVal *pcv    共通変数へのポインタ
  55.  */
  56. void drawCell(ComVal *pcv)
  57. {
  58.     int iX, iY;
  59.     int iValue;
  60.     LPoint lpt;
  61.  
  62.     for (iY = 0; iY < pcv->gridY; iY++) {
  63.         /* 左端表示座標位置.ここからセルごとに右に書いていく */
  64.         for (iX = 0; iX < pcv->gridX; iX++) {
  65.             lpt = GRID(iX, iY);
  66.             /*** 開始前の場合 ***/
  67.             if (pcv->sTrends == IDT_BEFORE) {
  68.                 drawPat3(pcv->btnImg[0], lpt);
  69.                 continue;
  70.             }
  71.  
  72.             /*** ゲーム開始後の場合 ***/
  73.             if (pcv->sTrends == IDT_BEGIN || pcv->sTrends == IDT_PLAYING) {
  74.                 switch (pcv->fCheck[iY][iX]) {
  75.                 case IDC_FLAG:    /* 旗        */
  76.                     drawMark(pcv, iX, iY, IDC_FLAG);
  77.                     break;
  78.                 case IDC_QMARK:    /* ?マーク    */
  79.                     drawMark(pcv, iX, iY, IDC_QMARK);
  80.                     break;
  81.                 case IDC_FACE:    /* 未オープン    */
  82.                     drawPat3(pcv->btnImg[0], lpt);
  83.                     break;
  84.                 case IDC_RBOM:    /* 赤爆弾    */
  85.                     drawPat3(pcv->btnImg[2], lpt);
  86.                     break;
  87.                 case IDC_CBOM:    /* ばってん爆弾    */
  88.                     drawPat3(pcv->btnImg[4], lpt);
  89.                     break;
  90.                 case IDC_OPEN:    /* オープン済み    */
  91.                     /* 指定セルのステータスを取得する */
  92.                     switch (iValue = pcv->fMap[iY][iX]) {
  93.                     case IDV_PLAIN: /* 無印オープンセルの場合 */
  94.                         drawPat3(pcv->btnImg[1], lpt);
  95.                         break;
  96.                     case IDV_BOM:
  97.                         drawPat3(pcv->btnImg[3], lpt);
  98.                         break;
  99.                     default:
  100.                         /* 数字オープンセルの場合 */
  101.                         if (iValue >= IDV_VAL1 && iValue <= IDV_VAL8)
  102.                             drawPat3(pcv->numImg[iValue - 1], lpt);
  103.                         break;
  104.                     }
  105.                     break;
  106.                 }
  107.             /*** ゲーム終了後 ***/
  108.             } else {
  109.                 switch (pcv->fCheck[iY][iX]) {
  110.                 case IDC_FLAG:    /* 旗        */
  111.                     drawMark(pcv, iX, iY, IDC_FLAG);
  112.                     break;
  113.                 case IDC_FACE:    /* 未オープン    */
  114.                     drawPat3(pcv->btnImg[0], lpt);
  115.                     break;
  116.                 case IDC_RBOM:    /* 赤爆弾    */
  117.                     drawPat3(pcv->btnImg[3], lpt);
  118.                     break;
  119.                 case IDC_CBOM:    /* ばってん爆弾    */
  120.                     drawPat3(pcv->btnImg[4], lpt);
  121.                     break;
  122.                 default:
  123.                     /* 指定セルのステータスを取得する */
  124.                     switch (pcv->fMap[iY][iX]) {
  125.                     case IDV_PLAIN: /* 無印オープンセルの場合 */
  126.                         drawPat3(pcv->btnImg[1], lpt);
  127.                         break;
  128.                     case IDV_BOM: /* 爆弾オープンセルの場合 */
  129.                         drawPat3(pcv->btnImg[2], lpt);
  130.                         break;
  131.                     default: /* 数字オープンセルの場合 */
  132.                         drawPat3(pcv->numImg[pcv->fMap[iY][iX] - 1], lpt);
  133.                         break;
  134.                     }
  135.                     break;
  136.                 }
  137.             }
  138.         }
  139.     }
  140. }
  141.  
  142. /******************************************************************************
  143.  *    changeLevel():    セルマップのサイズと爆弾数を変更する
  144.  ******************************************************************************
  145.  *    引数:    int num        選択されたメニューアイテムの番号
  146.  *        ComVal *pcv    共通変数へのポインタ
  147.  */
  148. void changeLevel(ComVal *pcv, int num)
  149. {
  150.     switch (num) {
  151.     case 1:                /* ビギナークラス    */
  152.         pcv->gridY = pcv->gridX = pcv->bombNum = 10;
  153.         pcv->level = IDL_BEG;    /* ゲームレベル        */
  154.         break;
  155.     case 2:                /* ミドルクラス        */
  156.         pcv->gridY = 16;
  157.         pcv->gridX = 16;
  158.         pcv->bombNum = 40;
  159.         pcv->level = IDL_MID;
  160.         break;
  161.     case 3:                /* エキスパートクラス    */
  162.         pcv->gridY = 16;
  163.         pcv->gridX = 30;
  164.         pcv->bombNum = 99;
  165.         pcv->level = IDL_EXP;
  166.         break;
  167.     }
  168.  
  169.     /* 再描画するウィンドウサイズ変更 */
  170.     WMSize(pcv->windowPtr, WSIZE(pcv->gridX, pcv->gridY), 0);
  171.  
  172.     /* 再描画処理 */
  173.     regame(pcv);
  174. }
  175.  
  176. /******************************************************************************
  177.  *    enterDlg():    ベストタイム登録用ダイアログ作成
  178.  ******************************************************************************
  179.  *    引数:    ComVal *pcv    共通変数へのポインタ
  180.  */
  181. void enterDlg(ComVal *pcv)
  182. {
  183.     int i;
  184.     Rect rc;
  185.     Dialog dialog;            /* ダイアログレコード        */
  186.     Dialog *dialogPtr = &dialog;    /* ダイアログポインタ(疑似ポインタ)*/
  187.  
  188.     /* ベストタイム登録用ダイアログの表示位置 */
  189.     static Rect dlgPos = { DLG1_X, DLG1_Y, DLG1_X + DLG1_H, DLG1_Y + DLG1_V };
  190.     static Rect rcText = { 32 - 2, 48 - 2, 140 + 2, 60 + 2 };
  191.  
  192.     /* SX-WINDOW ver2.0以上の場合は、ダイアログの表示位置を画面の中央に
  193.        配置するように補正する */
  194.     TSAdjustRect(&rc, &dlgPos, 16);    /* 768*512の画面を基準に補正    */
  195.     dialogPtr = DMOpen(dialogPtr, &rc, NONTITLE, FALSE, WI_DLG << 4,
  196.         W_FRONT, FALSE, LONGWORD(1, TSGetID()), pcv->resDiEnt);
  197.     if (dialogPtr == NULL) {
  198.         DMError(D_CONFIRM, "タイアログが作成できません。");
  199.         return;
  200.     }
  201.     /* 編集可能テキストの文字列をクリアする */
  202.     setDItemText(dialogPtr, 1, NONTITLE);
  203.  
  204.     WMShow(&dialogPtr->window);    /* ダイアログを表示する        */
  205.     GMSetGraph(&dialogPtr->window.graph);
  206.     GMAPage(G_PAGE0 | G_PAGE1);    /* アクセスページを0と1ページにする */
  207.     GMForeColor(G_BLACK);
  208.     GMBackColor(G_LGRAY);
  209.     /* ダイアログタイトル */
  210.     GMShadowStrZ("ベストプレーヤーの登録", LONGWORD((DLG1_H - 11 * 12) / 2, 4));
  211.     GMShadowStrZ("プレーヤーの名前", LONGWORD(30, 32));
  212.  
  213.     /* 名前入力欄 */
  214.     GMBackColor(G_WHITE);
  215.     GMShadowRect(&rcText);
  216.  
  217.     DMDraw(dialogPtr);
  218.     while (1) {
  219.         i = DMControl(enterFilter);
  220.         if (i == 2) {
  221.             /* [確認]ボタンが押された */
  222.             /* 編集可能テキストの文字列を取得する */
  223.             getDItemText(dialogPtr, 1, pcv->player);
  224.             break;
  225.         }
  226.     }
  227.     GMBackColor(G_LGRAY);
  228.     DMClose(dialogPtr);        /* ダイアログをクローズする    */
  229. }
  230.  
  231. /******************************************************************************
  232.  *    enterFilter():    ダイアログ上のイベント処理
  233.  ******************************************************************************
  234.  *    引数:    Dialog *dlgPtr    ダイアログポインタ
  235.  *        Event *pev    イベントレコードへのポインタ
  236.  *    戻り値:    int        0以外: DMControlの返り値
  237.  */
  238. int enterFilter(Dialog *dlgPtr, Event *pev)
  239. {
  240.     switch (pev->what) {
  241.     case E_KEYDOWN:
  242.         if (pev->whom.key.ascii == '\r')
  243.             return 2;
  244.         break;
  245.     case E_IDLE:            /* アイドルイベント、その他のイベント */
  246.     default:
  247.         /* カーソルの点滅 */
  248.         TMIdle(dlgPtr->tEdit);
  249.         break;
  250.     }
  251.  
  252.     return 0;
  253. }
  254.  
  255. /******************************************************************************
  256.  *    recordDlg():    ベストタイム表示用ダイアログ作成
  257.  ******************************************************************************
  258.  *    引数:    ComVal *pcv    共通変数へのポインタ
  259.  */
  260. void recordDlg(ComVal *pcv)
  261. {
  262.     int i;
  263.     char szScrName[TS_NAMEMAX], str[64];
  264.     FILE *fn;
  265.     Rect rc;
  266.     Dialog dialog;            /* ダイアログレコード        */
  267.     Dialog *dialogPtr = &dialog;    /* ダイアログポインタ(疑似ポインタ)*/
  268.  
  269.     /* ベストタイム表示用ダイアログの表示位置 */
  270.     static Rect dlgPos = { DLG2_X, DLG2_Y, DLG2_X + DLG2_H, DLG2_Y + DLG2_V };
  271.  
  272.     /* SX-WINDOW ver2.0以上の場合は、ダイアログの表示位置を画面の中央に
  273.        配置するように補正する */
  274.     TSAdjustRect(&rc, &dlgPos, 16);    /* 768*512の画面を基準に補正    */
  275.     dialogPtr = DMOpen(dialogPtr, &rc, NONTITLE, TRUE, WI_DLG << 4,
  276.         W_FRONT, FALSE, LONGWORD(2, TSGetID()), pcv->resDiRec);
  277.     if (dialogPtr == NULL) {
  278.         DMError(D_CONFIRM, "タイアログが作成できません。");
  279.         return;
  280.     }
  281.     strcpy(szScrName, pcv->myPath);
  282.     strcat(szScrName, "爆弾ゲーム.scr");
  283.  
  284.     /* ベストタイム保持ファイルオープン */
  285.     fn = fopen(szScrName, "rb");
  286.     if (fn == NULL) {
  287.         strcpy(pcv->record[0], "999秒");
  288.         strcpy(pcv->record[1], "999秒");
  289.         strcpy(pcv->record[2], "999秒");
  290.     /* ファイルオープン成功なら */
  291.     } else {
  292.         /* レベルごとの文字列を取得する */
  293.         for (i = 0; i < 3; i++) {
  294.             fgets(pcv->record[i], BUFF_SIZE, fn);
  295.             pcv->record[i][strlen(pcv->record[i]) - 1] = 0;
  296.         }
  297.         fclose(fn);
  298.     }
  299.     GMSetGraph(&dialogPtr->window.graph);
  300.     GMAPage(G_PAGE0 | G_PAGE1);    /* アクセスページを0と1ページにする */
  301.     GMForeColor(G_BLACK);
  302.     GMBackColor(G_LGRAY);
  303.  
  304.     /* ダイアログタイトル */
  305.     GMShadowStrZ("ベストプレーヤー", LONGWORD((DLG2_H - 8 * 12) / 2, 4));
  306.     sprintf(str, "ビギナークラス  %s\0", pcv->record[0]);
  307.     GMShadowStrZ(str, LONGWORD(10, 40));
  308.     sprintf(str, "ミドルクラス    %s\0", pcv->record[1]);
  309.     GMShadowStrZ(str, LONGWORD(10, 60));
  310.     sprintf(str, "エキスパートクラス %s\0", pcv->record[2]);
  311.     GMShadowStrZ(str, LONGWORD(10, 80));
  312.  
  313.     DMDraw(dialogPtr);
  314.     while (1) {
  315.         i = DMControl(recordFilter);
  316.         if (i == 1)
  317.             break;
  318.     }
  319.     DMClose(dialogPtr);        /* ダイアログをクローズする    */
  320. }
  321.  
  322. /******************************************************************************
  323.  *    recordFilter():    ダイアログ上のイベント処理
  324.  ******************************************************************************
  325.  *    引数:    Dialog *dlgPtr    ダイアログポインタ
  326.  *        Event *pev    イベントレコードへのポインタ
  327.  *    戻り値:    int        0以外: DMControlの返り値
  328.  */
  329. int recordFilter(Dialog *dlgPtr, Event *pev)
  330. {
  331.     if (pev->what == E_KEYDOWN && pev->whom.key.ascii == '\r')
  332.         return 1;
  333.  
  334.     return 0;
  335. }
  336.  
  337. /******************************************************************************
  338.  *    setDItemText():    ダイアログアイテムの編集可能テキストへの文字列の設定
  339.  ******************************************************************************
  340.  *    引数:    Dialog *dlgPtr    ダイアログポインタ
  341.  *        int num        ダイアログのアイテム番号
  342.  *        _LASCII str    設定するLASCII型文字列
  343.  */
  344. void setDItemText(Dialog *dlgPtr, int num, _LASCII str)
  345. {
  346.     short type;
  347.     Rect rc;
  348.     Handle item;
  349.  
  350.     /* ダイアログアイテムのハンドルを取得する */
  351.     DIGet(dlgPtr, num, &type, &item, &rc);
  352.     DITSet(type, item, str);    /* 編集可能テキストに文字列を設定する */
  353. }
  354.  
  355. /******************************************************************************
  356.  *    getDItemText():    ダイアログアイテムの編集可能テキストの文字列の取得
  357.  ******************************************************************************
  358.  *    引数:    Dialog *dlgPtr    ダイアログポインタ
  359.  *        int num        ダイアログのアイテム番号
  360.  *        _LASCII str    LASCII型文字列を格納するポインタ
  361.  */
  362. void getDItemText(Dialog *dlgPtr, int num, _LASCII str)
  363. {
  364.     short type;
  365.     Rect rc;
  366.     Handle item;
  367.  
  368.     /* ダイアログアイテムのハンドルを取得する */
  369.     DIGet(dlgPtr, num, &type, &item, &rc);
  370.     DITGet(type, item, str);    /* 編集可能テキストの文字列を取得する */
  371.     str[str[0] + 1] = 0;        /* 文字列の最後に0を付加する    */
  372. }
  373.  
  374. /******************************************************************************
  375.  *    mountImgRes():    ビットイメージのハンドルを確保
  376.  ******************************************************************************
  377.  *    引数:    ComVal *pcv    共通変数へのポインタ
  378.  *    戻り値:    BOOLEAN        = TRUE:  正常終了
  379.  *                = FALSE: 異常終了
  380.  */
  381. BOOLEAN mountImgRes(ComVal *pcv)
  382. {
  383.     int i;
  384.  
  385.     /* ハンドルを格納する配列の初期化 */
  386.     for (i = 0; i < 8; i++)
  387.         pcv->btnImg[i] = NULL;
  388.     for (i = 0; i < 8; i++)
  389.         pcv->numImg[i] = NULL;
  390.     for (i = 0; i < 4; i++)
  391.         pcv->bombImg[i] = NULL;
  392.     pcv->resDiEnt = NULL;
  393.     pcv->resDiRec = NULL;
  394.  
  395.     /* "爆弾ゲーム.lb"をカレントリソースにする */
  396.     if (!loadResource(pcv))
  397.         return FALSE;
  398.  
  399.     /* 各種フィールド用のイメージデータの取得 */
  400.     for (i = 0; i < 8; i++) {
  401.         pcv->btnImg[i] = TSRscGet('PAT3', 2000 + i);
  402.         if (pcv->btnImg[i] == NULL)
  403.             return FALSE;
  404.     }
  405.     /* 各種フィールド用のイメージデータの取得(1~8の番号のマス) */
  406.     for (i = 0; i < 8; i++) {
  407.         /* リソースハンドルを取得する */
  408.         pcv->numImg[i] = TSRscGet('PAT3', 1001 + i);
  409.         if (pcv->numImg[i] == NULL)
  410.             return FALSE;
  411.     }
  412.     /* 爆弾の個数を示すのイメージデータの取得 */
  413.     for (i = 0; i < 4; i++) {
  414.         /* リソースハンドルを取得する */
  415.         pcv->bombImg[i] = TSRscGet('PAT4', 1000 + i);
  416.         if (pcv->bombImg[i] == NULL)
  417.             return FALSE;
  418.     }
  419.     pcv->resDiEnt = TSRscGet('DITL', 1000);
  420.     if (pcv->resDiEnt == NULL)
  421.         return FALSE;
  422.  
  423.     pcv->resDiRec = TSRscGet('DITL', 1001);
  424.     if (pcv->resDiRec == NULL)
  425.         return FALSE;
  426.  
  427.     return TRUE;
  428. }
  429.  
  430. /******************************************************************************
  431.  *    loadResource():    ダイアログのリソースファイルを読み出す
  432.  ******************************************************************************
  433.  *    引数:    ComVal *pcv    共通変数へのポインタ
  434.  *    戻り値:    BOOLEAN     = TRUE:  読み込み成功
  435.  *                = FALSE: 読み込み失敗
  436.  */
  437. BOOLEAN loadResource(ComVal *pcv)
  438. {
  439.     int errCode;
  440.     Handle resHdl;
  441.     Task task;            /* タスク管理レコード        */
  442.     char drv[2], path[65], node[19], ext[5];
  443.     char fWork[TS_NAMEMAX];
  444.  
  445.     TSGetTdb(&task, TS_OWN);    /* タスク管理レコードを取得する    */
  446.     strsfn(task.name, drv, path, node, ext); /* タスク名を分解する    */
  447.     strmfn(fWork, drv, path, "", ""); /* 検索パスを作成する        */
  448.     /* リソースファイルを検索する */
  449.     errCode = TSSearchFile("爆弾ゲーム.LB", fWork, fWork);
  450.     if (errCode < 0) {        /* リソースファイルが見付からない */
  451.         DMError(D_CONFIRM, "リソースファイル「爆弾ゲーム.LB」が\r"
  452.                    "見付かりません。");
  453.         return FALSE;
  454.     }
  455.     resHdl = TSResOpen(fWork);    /* リソースのオープン */
  456.     if (resHdl == NULL) {
  457.         DMError(D_CONFIRM, "リソースファイル「爆弾ゲーム.LB」が\r"
  458.                    "オープンできません。");
  459.         return FALSE;
  460.     }
  461.     errCode = TSResLoad();
  462.     if (errCode < 0) {
  463.         DMError(D_CONFIRM, "リソースファイルが読み込めません。");
  464.         /* カレントリソースの削除とリソースファイルのクローズ
  465.            -->TSResDisposeではクローズしないのでダメ!*/
  466.         TSResRemove();
  467.         return FALSE;
  468.     }
  469.  
  470.     return TRUE;
  471. }
  472.  
  473. /******************************************************************************
  474.  *    drawPat3():    パターンハンドル('PAT3')の描画
  475.  ******************************************************************************
  476.  *    引数:    RectImg **phdl    'PAT3'のハンドル
  477.  *        LPoint lpt    表示座標
  478.  */
  479. void drawPat3(RectImg **phdl, LPoint lpt)
  480. {
  481.     MMHdlLock(phdl);        /* ハンドルをロック        */
  482.     GMPutRImg(*phdl, lpt);        /* レクタングルイメージを描画    */
  483.     MMHdlUnlock(phdl);        /* ハンドルのロックを解除    */
  484. }
  485.  
  486. /******************************************************************************
  487.  *    drawPat4():    マスク付パターンハンドル('PAT4')の描画
  488.  ******************************************************************************
  489.  *    引数:    RectImg **phdl    'PAT4'のハンドル
  490.  *        LPoint lpt    表示座標
  491.  */
  492. void drawPat4(RectImg **phdl, LPoint lpt)
  493. {
  494.     int lastAP;
  495.     Rect rc;
  496.     RectImg *iptr;
  497.  
  498.     MMHdlLock(phdl);        /* ハンドルをロック        */
  499.     iptr = *phdl;
  500.     rc = iptr->bounds;
  501.     GMSlideRect(&rc, lpt);
  502.     /* アクセスページを0~2ページにする */
  503.     lastAP = GMAPage(G_PAGE0 | G_PAGE1 | G_PAGE2);
  504.     GMPlotImg(iptr->data, &rc, 3 << 8); /* image のプット        */
  505.     GMAPage(lastAP);
  506.     MMHdlUnlock(phdl);        /* ハンドルのロックを解除    */
  507. }
  508.  
  509. /******************************************************************************
  510.  *    getParam():
  511.  ******************************************************************************
  512.  *    引数:    char **tbuff    コマンドラインのアドレステーブル
  513.  *    注釈:    '-C?'(ゲームクラス設定)のオプションスイッチをサポート
  514.  */
  515. void getParam(ComVal *pcv, char **tbuff)
  516. {
  517.     int i, ct;
  518.     char *cp;
  519.  
  520.     ct = (int) *tbuff++;
  521.     if (ct > 0) {            /* オプションスイッチの有無    */
  522.         for (i = 0; i < ct; i++) {
  523.             cp = *tbuff++;
  524.             if (*cp == '-' || *cp == '/') {
  525.                 cp++;
  526.                 switch (*cp++) {
  527.                 case 'C': /* ゲームレベルの設定    */
  528.                 case 'c':
  529.                     switch (*cp++) {
  530.                     case '0': /* ビギナークラス    */
  531.                         pcv->gridY = 10;
  532.                         pcv->gridX = 10;
  533.                         pcv->bombNum = 10;
  534.                         pcv->level = IDL_BEG; /* ゲームレベル */
  535.                         break;
  536.                     case '1': /* ミドルクラス    */
  537.                         pcv->gridY = 16;
  538.                         pcv->gridX = 16;
  539.                         pcv->bombNum = 40;
  540.                         pcv->level = IDL_MID;
  541.                         break;
  542.                     case '2': /* エキスパートクラス */
  543.                         pcv->gridY = 16;
  544.                         pcv->gridX = 30;
  545.                         pcv->bombNum = 99;
  546.                         pcv->level = IDL_EXP;
  547.                         break;
  548.                     }
  549.                     break;
  550.                 }
  551.             }
  552.         }
  553.     }
  554. }
  555.  
  556. /******************************************************************************
  557.  *    initMap():    セルマップの初期化
  558.  ******************************************************************************
  559.  *    引数:    ComVal *pcv    共通変数へのポインタ
  560.  *        CPoint *pcpt
  561.  */
  562. void initMap(ComVal *pcv, CPoint *pcpt)
  563. {
  564.     int di = 0, dj = 0, dk = 0;
  565.     register int i;
  566.     register int iLim, iBom;
  567.     register int iX, iY;
  568.  
  569.     /* 爆弾の配置 */
  570.     srand(EMSysTime() + LONGWORD(pcpt->x, pcpt->y));
  571.     iLim = (pcv->gridX * pcv->gridY) - 1;
  572.     for (i = 0; i < pcv->bombNum; i++) {
  573.         iBom = rand();
  574.         iBom %= iLim;
  575.         iX = iBom % pcv->gridX;
  576.         iY = iBom / pcv->gridX;
  577.         dk++;
  578.         if (pcv->fMap[iY][iX] == IDV_BOM) {
  579.             i--;
  580.             di++;
  581.             continue;
  582.         }
  583.         if (iX == pcpt->x && iY == pcpt->y) {
  584.             i--;
  585.             dj++;
  586.             continue;
  587.         }
  588.         pcv->fMap[iY][iX] = IDV_BOM;
  589.     }
  590.  
  591.     /* 爆弾セル以外のボリューム設定 */
  592.     for (iY = 0; iY < pcv->gridY; iY++)
  593.         for (iX = 0; iX < pcv->gridX; iX++)
  594.             if (pcv->fMap[iY][iX] != IDV_BOM) /* 爆弾セルでなければ */
  595.                 setValue(pcv, iX, iY); /* セルボリューム設定 */
  596. }
  597.  
  598. /******************************************************************************
  599.  *    clearGame():    ゲームクリア処理
  600.  ******************************************************************************
  601.  *    引数:    ComVal *pcv    共通変数へのポインタ
  602.  */
  603. void clearGame(ComVal *pcv)
  604. {
  605.     int iX, iY;
  606.  
  607.     /**** CLEAR!!!****/
  608.     pcv->sTrends = IDT_CLEAR;    /* ゲーム進行状況フラグ = ゲームクリアー */
  609.  
  610.     /* 残ったセルに旗を立てる */
  611.  
  612.     for (iY = 0; iY < pcv->gridY; iY++) {
  613.         for (iX = 0; iX < pcv->gridX; iX++) {
  614.             if (pcv->fCheck[iY][iX] != IDC_OPEN) {
  615.                 /* 旗を描く */
  616.                 drawPat3(pcv->btnImg[6], GRID(iX, iY));
  617.                 pcv->fCheck[iY][iX] = IDC_FLAG;
  618.             }
  619.         }
  620.     }
  621.     /* 残り爆弾数消去 */
  622.     pcv->restFlag = 0;
  623.     drawZan(pcv);
  624.  
  625.     /* ベストタイム保持処理 */
  626.     bestTime(pcv);
  627. }
  628.  
  629. /******************************************************************************
  630.  *    regame():    再ゲーム開始処理
  631.  ******************************************************************************
  632.  *    引数:    ComVal *pcv    共通変数へのポインタ
  633.  */
  634. void regame(ComVal *pcv)
  635. {
  636.     int iX, iY;
  637.  
  638.     pcv->restCell = pcv->gridX * pcv->gridY; /* 未処理セル数 */
  639.     pcv->restFlag = pcv->bombNum;    /* 残り旗数        */
  640.     pcv->sTrends = IDT_BEFORE;    /* ゲーム進行状況(開始前) */
  641.     pcv->seconds = 0;        /* 経過タイム        */
  642.  
  643.     /* セルマップの初期化 */
  644.     for (iY = 0; iY < pcv->gridY; iY++) {
  645.         for (iX = 0; iX < pcv->gridX; iX++) {
  646.             pcv->fMap[iY][iX] = IDV_PLAIN;
  647.             pcv->fCheck[iY][iX] = IDC_FACE;
  648.         }
  649.     }
  650.     addUpdate(pcv->windowPtr, NULL); /* ウィンドウ内全体を再描画する */
  651. }
  652.  
  653. /******************************************************************************
  654.  *    bestTime():    ベストタイム変更処理
  655.  ******************************************************************************
  656.  *    引数:    ComVal *pcv    共通変数へのポインタ
  657.  */
  658. void bestTime(ComVal *pcv)
  659. {
  660.     int iTime, i;
  661.     FILE *fn;
  662.     char szScrName[TS_NAMEMAX];
  663.  
  664.     strcpy(szScrName, pcv->myPath);
  665.     strcat(szScrName, "爆弾ゲーム.scr");
  666.  
  667.     /* ベストタイム保持ファイルオープン */
  668.     fn = fopen(szScrName, "rb");
  669.     if (fn == NULL) {
  670.         /* デフォルトのデータを書き込む */
  671.         strcpy(pcv->record[0], "999秒");
  672.         strcpy(pcv->record[1], "999秒");
  673.         strcpy(pcv->record[2], "999秒");
  674.     /* ファイルオープン成功なら */
  675.     } else {
  676.         /* レベルごとの文字列を取得する */
  677.         for (i = 0; i < 3; i++) {
  678.             fgets(pcv->record[i], BUFF_SIZE, fn);
  679.             pcv->record[i][strlen(pcv->record[i]) - 1] = 0;
  680.         }
  681.         fclose(fn);        /* 現在のファイルをクローズ */
  682.     }
  683.     /* 現在のゲームレベルでのベストタイムを参照 */
  684.     iTime = atoi(pcv->record[pcv->level]);
  685.     /* 今回のタイムがベストタイムかどうか */
  686.     /* ベストじゃなければリターン */
  687.     if (pcv->seconds >= iTime)
  688.         return;
  689.  
  690.     /* ベストタイム保持用のダイアログを作成 */
  691.     enterDlg(pcv);
  692.  
  693.     fn = fopen(szScrName, "wb");        /* 新たに同名ファイルを作成 */
  694.     if (fn == NULL)
  695.         return;
  696.  
  697.     /* ベストタイム更新! スコアファイルの書き換え */
  698.     sprintf(pcv->record[pcv->level], "%3d秒 %s\0", pcv->seconds, &pcv->player[1]);
  699.     for (i = 0; i < 3; i++) {
  700.         fwrite((unsigned char *) pcv->record[i], sizeof(char), strlen(pcv->record[i]), fn);
  701.         fwrite((unsigned char *) "\n", sizeof(char), 1, fn);
  702.     }
  703.     /* スコアファイルをクローズ */
  704.     fclose(fn);
  705.  
  706.     /* ベストタイム表示ダイアログ作成 */
  707.     recordDlg(pcv);
  708. }
  709.  
  710. /******************************************************************************
  711.  *    drawBitmap():    指定位置のセルを開く
  712.  ******************************************************************************
  713.  *    引数:    ComVal *pcv    共通変数へのポインタ
  714.  *        CPoint *pcpt    セル位置(x,y)へのポインタ
  715.  */
  716. void drawBitmap(ComVal *pcv, CPoint *pcpt)
  717. {
  718.     unsigned char iValue;
  719.  
  720.     GMSetGraph(&pcv->windowPtr->graph); /* 自分をカレントグラフにする */
  721.  
  722.     iValue = pcv->fMap[pcpt->y][pcpt->x]; /* 指定セルのステータス */
  723.     switch (iValue) {
  724.     case IDV_BOM:
  725.         /* ゲームオーバー! */
  726.         openAllBomb(pcv, pcpt);
  727.         break;
  728.     case IDV_VAL1:
  729.     case IDV_VAL2:
  730.     case IDV_VAL3:
  731.     case IDV_VAL4:
  732.     case IDV_VAL5:
  733.     case IDV_VAL6:
  734.     case IDV_VAL7:
  735.     case IDV_VAL8:
  736.         drawPat3(pcv->numImg[iValue - 1], GRID(pcpt->x, pcpt->y));
  737.         pcv->restCell--;    /* 未処理セル数を1つ減らす    */
  738.         pcv->fCheck[pcpt->y][pcpt->x] = IDC_OPEN; /* オープン済    */
  739.         break;
  740.     case IDV_PLAIN:
  741.         /* セルを開く */
  742.         safetyZone(pcv, pcpt);
  743.         break;
  744.     }
  745. }
  746.  
  747. /******************************************************************************
  748.  *    drawMark():    旗と?マークの描画、描き換えを行う
  749.  ******************************************************************************
  750.  *    引数:    ComVal *pcv    共通変数へのポインタ
  751.  *        int iX        セル位置
  752.  *        int iY
  753.  *        char fMark    書き換えるセルの属性
  754. */
  755. void drawMark(ComVal *pcv, int iX, int iY, unsigned char fMark)
  756. {
  757.     LPoint lpt;
  758.  
  759.     GMSetGraph(&pcv->windowPtr->graph); /* 自分をカレントグラフにする */
  760.     /* 指定セルの位置を取得する */
  761.     lpt = GRID(iX, iY);
  762.  
  763.     switch (fMark) {
  764.     case IDC_FACE:            /* 未処理状態            */
  765.         drawPat3(pcv->btnImg[0], lpt); /* セルを描き換え    */
  766.         break;
  767.     case IDC_FLAG:            /* 旗                */
  768.         drawPat3(pcv->btnImg[6], lpt);
  769.         break;
  770.     case IDC_QMARK:            /* ?マーク            */
  771.         drawPat3(pcv->btnImg[5], lpt);
  772.         break;
  773.     }
  774. }
  775.  
  776. /******************************************************************************
  777.  *    setValue():    セルボリュームの設定(爆弾セル以外)
  778.  ******************************************************************************
  779.  *    引数:    ComVal *pcv    共通変数へのポインタ
  780.  *        int iX        セル位置
  781.  *        int iY
  782. */
  783. void setValue(ComVal *pcv, int iX, int iY)
  784. {
  785.     int i, j, cx, cy;
  786.  
  787.     /* 自分の周囲セルの爆弾数をカウントして、その数値を自分のボリュームとする */
  788.     for (i = -1; i <= 1; i++) {
  789.         cy = iY + i;
  790.         for (j = -1; j <= 1; j++) {
  791.             cx = iX + j;
  792.             /* 自分セルでなく、セルマップからはみださないことが検索条件 */
  793.             if (cx < 0 || cx >= pcv->gridX || cy < 0 || cy >= pcv->gridY)
  794.                 continue;
  795.  
  796.             if (pcv->fMap[cy][cx] == IDV_BOM)
  797.                 pcv->fMap[iY][iX] += 1;
  798.         }
  799.     }
  800. }
  801.  
  802. /******************************************************************************
  803.  *    safetyZone():    広範囲の爆弾のないエリア(SafeZone)を開く
  804.  ******************************************************************************
  805.  *    引数:    ComVal *pcv    共通変数へのポインタ
  806.  *        CPoint *pcpt    セル位置へのポインタ
  807. */
  808. void safetyZone(ComVal *pcv, CPoint *pcpt)
  809. {
  810.     int iCheck;
  811.     CPoint cpt;
  812.  
  813.     /* 指定のセルが盤からはみ出していたらリターン */
  814.     if (pcpt->x < 0 || pcpt->x >= pcv->gridX || pcpt->y < 0 || pcpt->y >= pcv->gridY)
  815.         return;
  816.  
  817.     /* 自分のセルがすでに開いてる、または旗が立っていたらリターン */
  818.     iCheck = pcv->fCheck[pcpt->y][pcpt->x];
  819.     if (iCheck == IDC_OPEN || iCheck == IDC_FLAG)
  820.         return;
  821.  
  822.     /* 自分セルを開く */
  823.     openCell(pcv, pcpt);
  824.     /* 自分のセルが数字だったらリターン */
  825.     if (pcv->fMap[pcpt->y][pcpt->x] != IDV_PLAIN)
  826.         return;
  827.  
  828.     cpt.x = pcpt->x - 1;
  829.     cpt.y = pcpt->y - 1;
  830.     safetyZone(pcv, &cpt);
  831.     cpt.x++;
  832.     safetyZone(pcv, &cpt);
  833.     cpt.x++;
  834.     safetyZone(pcv, &cpt);
  835.     cpt.x -= 2;
  836.     cpt.y++;
  837.     safetyZone(pcv, &cpt);
  838.     cpt.x += 2;
  839.     safetyZone(pcv, &cpt);
  840.     cpt.x -= 2;
  841.     cpt.y++;
  842.     safetyZone(pcv, &cpt);
  843.     cpt.x++;
  844.     safetyZone(pcv, &cpt);
  845.     cpt.x++;
  846.     safetyZone(pcv, &cpt);
  847. }
  848.  
  849. /******************************************************************************
  850.  *    openCell():    指定されたマスを無条件に開く
  851.  ******************************************************************************
  852.  *    引数:    ComVal *pcv    共通変数へのポインタ
  853.  *        CPoint *pcpt    セル位置へのポインタ
  854. */
  855. void openCell(ComVal *pcv, CPoint *pcpt)
  856. {
  857.     unsigned int iValue;
  858.     LPoint lpt;
  859.  
  860.     GMSetGraph(&pcv->windowPtr->graph); /* 自分をカレントグラフにする */
  861.     /* 指定セルの位置を取得する */
  862.     lpt = GRID(pcpt->x, pcpt->y);
  863.  
  864.     /* 指定されたマスのステータスを求める */
  865.     iValue = pcv->fMap[pcpt->y][pcpt->x];
  866.     /* 指定されたマスをオープン(描画)する */
  867.     switch (iValue) {
  868.     case IDV_PLAIN:
  869.         drawPat3(pcv->btnImg[1], lpt);
  870.         pcv->restCell--;    /* 未処理セル数を1つ減らす    */
  871.         pcv->fCheck[pcpt->y][pcpt->x] = IDC_OPEN; /* オープン済    */
  872.         break;
  873.     case IDV_VAL1:
  874.     case IDV_VAL2:
  875.     case IDV_VAL3:
  876.     case IDV_VAL4:
  877.     case IDV_VAL5:
  878.     case IDV_VAL6:
  879.     case IDV_VAL7:
  880.     case IDV_VAL8:
  881.         drawPat3(pcv->numImg[iValue - 1], lpt);
  882.         pcv->restCell--;    /* 未処理セル数を1つ減らす    */
  883.         pcv->fCheck[pcpt->y][pcpt->x] = IDC_OPEN; /* オープン済    */
  884.         break;
  885.     }
  886. }
  887.  
  888. /******************************************************************************
  889.  *    openAllBomb():    すべての爆弾のセルを開く
  890.  ******************************************************************************
  891.  *    引数:    ComVal *pcv    共通変数へのポインタ
  892.  *        CPoint *pcpt    中心とするセル位置へのポインタ
  893. */
  894. void openAllBomb(ComVal *pcv, CPoint *pcpt)
  895. {
  896.     int val;
  897.  
  898.     val = pcv->fMap[pcpt->y][pcpt->x]; /* 指定セルのステータス    */
  899.     if (val == IDV_BOM) {        /* 爆弾に当たったか?        */
  900.         /* 自分のセルをオープン */
  901.         drawPat3(pcv->btnImg[3], GRID(pcpt->x, pcpt->y));
  902.         pcv->fCheck[pcpt->y][pcpt->x] = IDC_RBOM;
  903.     }
  904.     searchMesh(pcv, pcpt);        /* 放射状に残りのを爆破する    */
  905.     /* ゲーム停止(終了)のためのフラグ等の変更 */
  906.     pcv->sTrends = IDT_OVER;
  907. }
  908.  
  909. /******************************************************************************
  910.  *    searchMesh():    放射状マスサーチ(爆弾セルを開く)
  911.  ******************************************************************************
  912.  *    引数:    ComVal *pcv    共通変数へのポインタ
  913.  *        CPoint *pcpt    中心とするセル位置へのポインタ
  914. */
  915. void searchMesh(ComVal *pcv, CPoint *pcpt)
  916. {
  917.     int i, j, x, y, cx, cy;
  918.  
  919.     x = pcpt->x;
  920.     y = pcpt->y;
  921.  
  922.     cx = pcv->gridX - x - 1;
  923.     cx = (cx > x) ? cx : x;        /* 横方向の最大ループ回数    */
  924.     cy = pcv->gridY - y - 1;
  925.     cy = (cy > y) ? cy : y;        /* 縦方向のループ回数    */
  926.     cx = (cx > cy) ? cx : cy;    /* 最大のループ回数    */
  927.  
  928.     for (i = 1; i < cx + 1; i++) {
  929.         for (j = x + 1; j < x + i + 1; j++)    /* 右上横 */
  930.             openBomb(pcv, j, y - i);
  931.         for (j = x - 1; j > x - i - 1; j--)    /* 左下横 */
  932.             openBomb(pcv, j, y + i);
  933.         for (j = y; j > y - i; j--)        /* 右上縦 */
  934.             openBomb(pcv, x + i, j);
  935.         for (j = y; j < y + i; j++)        /* 左下縦 */
  936.             openBomb(pcv, x - i, j);
  937.         for (j = x; j < x + i; j++)        /* 右下横 */
  938.             openBomb(pcv, j, y + i);
  939.         for (j = x; j > x - i; j--)        /* 左上横 */
  940.             openBomb(pcv, j, y - i);
  941.         for (j = y + 1; j < y + i + 1; j++)    /* 右下縦 */
  942.             openBomb(pcv, x + i, j);
  943.         for (j = y - 1; j > y - i - 1; j--)    /* 左上縦 */
  944.             openBomb(pcv, x - i, j);
  945.     }
  946. }
  947.  
  948. /******************************************************************************
  949.  *    openBomb():    爆弾をオープン
  950.  ******************************************************************************
  951.  *    引数:    ComVal *pcv    共通変数へのポインタ
  952.  *        int iX        中心とするセル位置
  953.  *        int iY
  954. */
  955. void openBomb(ComVal *pcv, int iX, int iY)
  956. {
  957.     unsigned char iValue, iCheck;
  958.     LPoint lpt;
  959.  
  960.     /* マップ外の座標なら無視 */
  961.     if (iX < 0 || iX >= pcv->gridX || iY < 0 || iY >= pcv->gridY)
  962.         return;
  963.  
  964.     iValue = pcv->fMap[iY][iX];
  965.     iCheck = pcv->fCheck[iY][iX];
  966.     lpt = GRID(iX, iY);
  967.     /* 未処理の爆弾なら */
  968.     if (iValue == IDV_BOM && iCheck == IDC_FACE) {
  969.         drawPat3(pcv->btnImg[2], lpt); /* オープン        */
  970.         pcv->fCheck[iY][iX] = IDC_OPEN;
  971.     /* 旗が間違って立っていたら */
  972.     } else if (iValue != IDV_BOM && iCheck == IDC_FLAG) {
  973.         drawPat3(pcv->btnImg[4], lpt); /* ばってん爆弾        */
  974.         pcv->fCheck[iY][iX] = IDC_CBOM;
  975.     }
  976. }
  977.  
  978. /******************************************************************************
  979.  *    timeCounter():    経過秒数表示処理を行う
  980.  ******************************************************************************
  981.  *    引数:    ComVal *pcv    共通変数へのポインタ
  982.  *        int iX        中心とするセル位置
  983.  *        int iY
  984. */
  985. void timeCounter(ComVal *pcv)
  986. {
  987.     int mints, iSec, newtime;
  988.     CPoint cpt;
  989.  
  990.     if (pcv->sTrends == IDT_PLAYING) {    /* ゲーム進行中なら */
  991.         newtime = EMSysTime();        /* 現在のシステム時間を取得する */
  992.         mints = (newtime - pcv->oldTime) / 100;
  993.         if (mints >= 1) {        /* 前回より1秒以上経過したら */
  994.             pcv->seconds += mints;
  995.             iSec = pcv->seconds % 10000;
  996.             /* タイムオーバー */
  997.             if (pcv->seconds > TIME_LIMIT) {
  998.                 TSErrDialogN(D_CONFIRM, "タイムオーバーです。");
  999.                 /* フィールドの中心 */
  1000.                 cpt.x = pcv->gridX / 2;
  1001.                 cpt.y = pcv->gridY / 2;
  1002.                 openAllBomb(pcv, &cpt);
  1003.                 return;
  1004.             }
  1005.             drawTime(pcv);
  1006.             pcv->oldTime = newtime;    /* 前回のシステム時間更新 */
  1007.         }
  1008.     } else if (pcv->sTrends == IDT_BEGIN) {    /* 開始時なら */
  1009.         pcv->oldTime = EMSysTime();    /* 開始システム時間を取得する */
  1010.                         /* 1/100秒単位で返ってくるので注意! */
  1011.         pcv->sTrends = IDT_PLAYING;    /*ゲーム進行中*/
  1012.     }
  1013. }
  1014.  
  1015. /******************************************************************************
  1016.  *    drawZan():    残り旗数の描画
  1017.  ******************************************************************************
  1018.  *    引数:    ComVal *pcv    共通変数へのポインタ
  1019. */
  1020. void drawZan(ComVal *pcv)
  1021. {
  1022.     int sc, tc, i;
  1023.     int lastFC, lastFK, lastFF, lastFM;
  1024.     Point pt;
  1025.     Rect rc;
  1026.  
  1027.     static Rect rcAll = { 0, 0, 1024, 1024 };
  1028.  
  1029.     /* 残数エリアの全体のレクタングル */
  1030.     rc.l.l_t = LONGWORD(MARGIN, MARGIN + INFO_HEIGHT - 24 - 1);
  1031.     rc.l.r_b = LONGWORD(pcv->windowPtr->graph.rect.d.right - MARGIN, MARGIN + INFO_HEIGHT);
  1032.     GMClipRect(&rc);
  1033.  
  1034.     lastFC = GMForeColor(G_LGRAY);
  1035.     rc.d.top++;
  1036.     GMFillRect(&rc);
  1037.  
  1038.     /* ゲームがクリアされているか? */
  1039.     if (pcv->sTrends == IDT_CLEAR) {
  1040.         /* おめでとうの表示 */
  1041.         pt.p.x = rc.d.left + ((rc.d.right - rc.d.left) / 2) - (8 * 16 / 2);
  1042.         pt.p.y = rc.d.top;
  1043.  
  1044.         GMForeColor(G_RED);            /* 赤 */
  1045.         lastFM = GMFontMode(G_PSET);
  1046.         lastFF = GMFontFace(G_BOLD | G_ITALIC);    /* 斜体強調 */
  1047.         lastFK = GMFontKind(G_ROM16);        /* 24dot ROM font */
  1048.         GMMove(pt.x_y);
  1049.         GMDrawStrZ("CLEAR!!!");
  1050.         GMFontFace(lastFF);
  1051.         GMFontKind(lastFK);
  1052.         GMFontMode(lastFM);
  1053.     } else {
  1054.         /* 爆弾残数の表示 */
  1055.         if (pcv->restFlag >= 0) {
  1056.             sc = pcv->restFlag / 10;    /* 10の位の数 */
  1057.             tc = pcv->restFlag % 10;    /* 1の位の数 */
  1058.  
  1059.             pt.p.x = rc.d.left;
  1060.             pt.p.y = rc.d.bottom - 24;
  1061.             for (i = 0; i < sc; i++) {
  1062.                 /* 10の位を描画する */
  1063.                 drawPat4(pcv->bombImg[1], pt.x_y);
  1064.                 pt.p.x += 24;
  1065.             }
  1066.  
  1067.             pt.p.y = rc.d.bottom - 16;
  1068.             for (i = 0; i < tc; i++) {
  1069.                 /* 1の位を描画する */
  1070.                 drawPat4(pcv->bombImg[0], pt.x_y);
  1071.                 pt.p.x += 16;
  1072.             }
  1073.         } else {
  1074.         /* マイナスの場合 */
  1075.             sc = abs(pcv->restFlag) / 10;    /* 10の位の数 */
  1076.             tc = abs(pcv->restFlag) % 10;    /* 1の位の数 */
  1077.             pt.p.x = rc.d.left;
  1078.             pt.p.y = rc.d.bottom - 24;
  1079.             for (i = 0; i < sc; i++) {
  1080.                 /* 10の位を描画する */
  1081.                 drawPat4(pcv->bombImg[3], pt.x_y);
  1082.                 pt.p.x += 24;
  1083.             }
  1084.  
  1085.             pt.p.y = rc.d.bottom - 16;
  1086.             for (i = 0; i < tc; i++) {
  1087.                 /* 1の位を描画する */
  1088.                 drawPat4(pcv->bombImg[2], pt.x_y);
  1089.                 pt.p.x += 16;
  1090.             }
  1091.         }
  1092.     }
  1093.     GMClipRect(&rcAll);
  1094.     GMForeColor(lastFC);
  1095. }
  1096.  
  1097. /******************************************************************************
  1098.  *    drawTime():    経過時間の描画
  1099.  ******************************************************************************
  1100.  *    引数:    ComVal *pcv    共通変数へのポインタ
  1101. */
  1102. void drawTime(ComVal *pcv)
  1103. {
  1104.     int lastFC, lastBC;
  1105.     char str[16];
  1106.  
  1107.     static Rect rctmmg = {
  1108.         TMMGX, TMMGY + MARGIN, TMMGX + TMWIDE, TMMGY + TMHEIGHT + MARGIN
  1109.     };
  1110.  
  1111.     lastBC = GMBackColor(G_WHITE);
  1112.     lastFC = GMForeColor(G_BLACK);
  1113.     GMShadowRect(&rctmmg);
  1114.  
  1115.     sprintf(str, "%4d\0", pcv->seconds);
  1116.     GMMove(LONGWORD(TMMGX + 2, TMMGY + 2 + MARGIN)); /* フレーム内文字の座標 */
  1117.     GMDrawStrZ(str);
  1118.  
  1119.     GMBackColor(lastBC);
  1120.     GMForeColor(lastFC);
  1121. }
  1122.  
  1123. /******************************************************************************
  1124.  *    drawRgBtn():    再ゲームボタンの描画
  1125.  ******************************************************************************
  1126.  *    引数:    ComVal *pcv    共通変数へのポインタ
  1127. */
  1128. void drawRgBtn(ComVal *pcv)
  1129. {
  1130.     Point pt;
  1131.  
  1132.     /* 再ゲームボタンのレクタングル */
  1133.     static Rect rcBtn = { 0, 0, RBTNWIDE, RBTNHEIGHT };
  1134.  
  1135.     /* 再設定ボタンの表示座標を設定 */
  1136.     pt.p.x = pcv->windowPtr->graph.rect.d.right - (RBTNMGX + RBTNWIDE);
  1137.     pt.p.y = pcv->windowPtr->graph.rect.d.top + MARGIN + RBTNMGY;
  1138.  
  1139.     /* 再設定ボタンのレクタングルを設定(参照用) */
  1140.     pcv->rcReplay = rcBtn;
  1141.     GMSlideRect(&pcv->rcReplay, pt.x_y);
  1142.     drawPat3(pcv->btnImg[7], pt.x_y);
  1143. }
  1144.  
  1145. /******************************************************************************
  1146.  *    checkPctBtn():    ピクチャーボタンのチェック
  1147.  ******************************************************************************
  1148.  *    引数:    ComVal *pcv    共通変数へのポインタ
  1149.  *        Rect *prc    ピクチャーボタンのレクタングルへのポインタ
  1150.  *        LPoint lpt    ポインタ座標(ローカル座標系)
  1151.  *    戻り値:    BOOLEAN        = TRUE:  ボタンが押された
  1152.  *                = FALSE: ボタンは押されてない
  1153.  */
  1154. BOOLEAN checkPctBtn(ComVal *pcv, Rect *prc, LPoint lpt)
  1155. {
  1156.     BOOLEAN ret = TRUE;
  1157.  
  1158.     if (!GMPtInRect(prc, lpt))
  1159.         return FALSE;
  1160.  
  1161.     revFillRect(prc);
  1162.     /* マウスボタンが離されるまでループ */
  1163.     while (EMLStill()) {
  1164.         lpt = EMMSLoc();
  1165.         if (GMPtInRect(prc, lpt)) {
  1166.             /* ボタン内にカーソルが移動 */
  1167.             if (!ret) {
  1168.             /* ボタンが押されてなければフレーム内を反転 */
  1169.                 revFillRect(prc);
  1170.                 ret = TRUE;
  1171.             }
  1172.         } else {
  1173.             /* ボタン外にカーソルが移動 */
  1174.             if (ret) {
  1175.             /* ボタンが押されていたならフレーム内を反転 */
  1176.                 revFillRect(prc);
  1177.                 ret = FALSE;
  1178.             }
  1179.         }
  1180.     }
  1181.     /* マウスボタンが離された場合の処理 */
  1182.     if (ret)
  1183.         /* ボタンが押されていればフレーム内を戻す */
  1184.         revFillRect(prc);
  1185.     /* ボタンが離された場所をチェック */
  1186.     if (!GMPtInRect(prc, lpt))
  1187.         return FALSE;
  1188.  
  1189.     return ret;
  1190. }
  1191.  
  1192. /******************************************************************************
  1193.  *    revFillRect():    レクタングル全体の反転
  1194.  ******************************************************************************
  1195.  *    引数:    Rect *prc    反転するレクタングルへのポインタ
  1196.  */
  1197. void revFillRect(Rect *prc)
  1198. {
  1199.     int lastAP, lastFC, lastPM;
  1200.  
  1201.     /* アクセスページを0と1ページにする */
  1202.     lastAP = GMAPage(G_PAGE0 | G_PAGE1);
  1203.     lastPM = GMPenMode(G_XOR);
  1204.     lastFC = GMForeColor(G_BLACK);
  1205.  
  1206.     GMFillRect(prc);
  1207.  
  1208.     GMForeColor(lastFC);
  1209.     GMPenMode(lastPM);
  1210.     GMAPage(lastAP);
  1211. }
  1212.  
  1213. /******************************************************************************
  1214.  *    revFrameRect():    レクタングルのフレームを反転
  1215.  ******************************************************************************
  1216.  *    引数:    Rect *prc    反転するレクタングルへのポインタ
  1217.  */
  1218. void revFrameRect(Rect *prc)
  1219. {
  1220.     int lastAP, lastFC, lastPM;
  1221.  
  1222.     /* アクセスページを0と1ページにする */
  1223.     lastAP = GMAPage(G_PAGE0 | G_PAGE1);
  1224.     lastPM = GMPenMode(G_XOR);
  1225.     lastFC = GMForeColor(G_BLACK);
  1226.  
  1227.     GMFrameRect(prc);
  1228.  
  1229.     GMForeColor(lastFC);
  1230.     GMPenMode(lastPM);
  1231.     GMAPage(lastAP);
  1232. }
  1233.